﻿#include "computermanager.h"
#include "syscfg.h"
#include "sendemailtask.h"
#include "TcpConnectHandler.h"

#include "commonreq.h"
#include "getapprunningstateres.h"


ComputerManager gComputerManager;

ComputerManager::ComputerManager()
{
    server = NULL;
    checkOfflineTimer = -1;
}

void WINAPI onOfflineTimerFired(UINT wTimerID, UINT msg, DWORD dwUser, DWORD dwl, DWORD dw2)
{
    gComputerManager.onOfflineCheckTimerFired();
}

void ComputerManager::start()
{

    gDBService.loadAllComputers(computers);

    QList<Computer>::iterator iter;
    for (iter = computers.begin(); iter != computers.end(); iter++)
    {
        QString *isRead = new QString("0");
        QString *alarmType = NULL;
        QString *alarmMode = NULL;
        gDBService.loadComputerAlarmLogsCount(iter->unReadALarmCount, &(iter->id), isRead, alarmType, alarmMode);
        SafeDeleteObj(isRead);
    }

    server = new TcpServer(LISTEN_PORT);
    server->run();

    checkOfflineTimer = timeSetEvent(1000, 1, (LPTIMECALLBACK)onOfflineTimerFired, DWORD(this), TIME_PERIODIC);

    gSendEmailTask.run();

}

void ComputerManager::stop()
{
    if(server)
    {
        server->stop();
        SafeDeleteObj(server);
    }
    if(checkOfflineTimer >= 0)
    {
       timeKillEvent(checkOfflineTimer);
       checkOfflineTimer = -1;
    }

}


void ComputerManager::onOfflineCheckTimerFired()
{
    lock.lock();
    QDateTime now = QDateTime::currentDateTime();
    int totalOffLineCount = 0;

    int totalUnReadAlarmLogCount = 0;
    for (QList<Computer>::iterator iter = computers.begin(); iter != computers.end(); iter++)
    {
        if(iter->isOffLine() != iter->isOffLine(now))
        {
        }

        totalOffLineCount += iter->isOffLine();
        totalUnReadAlarmLogCount += iter->unReadALarmCount;
    }


    lock.unlock();

    emit this->offlineAndALarmCountUpdate(totalOffLineCount, computers.size(), totalUnReadAlarmLogCount);
    emit this->computersUpdated();

}

QString ComputerManager::getAlarmInfoOfComputer(Computer &computer)
{
    QString content = "应用:" + computer.name + ",ip:" + computer.ip  + ",连接状态：" + computer.getOffLineState() + ",未读异常条数：" + int2QStr(computer.unReadALarmCount) +"\n";
    if(computer.unReadALarmCount > 10)
    {
        content += "未读告警较多。这里只显示最后十条：\n";
    }
    else
    {
        content += "未读告警如下：\n";
    }

    list<ComputerAlarmLog* > logs;
    QString isRead = "0";
    gDBService.loadComputerAlarmLogs(logs, &(computer.id), &isRead,NULL, NULL, 10);
    foreach (ComputerAlarmLog * log, logs) {
        content += log->sayInfo() + "\n";
    }

    SafeClearListAndDelEle(ComputerAlarmLog, logs);

    return content;
}

int ComputerManager::saveOneComputer(Computer &computer)
{
    if(f_success == gDBService.saveOneComputer(computer))
    {
        lock.lock();

        bool exist = false;

        for (QList<Computer>::iterator iter = computers.begin(); iter != computers.end(); iter++)
        {
            if(iter->id == computer.id)
            {
                exist  = true;
                iter->copyBasicInfo(computer);
            }
        }

        if(!exist)
        {
            computers.push_back(computer);
        }
        lock.unlock();

        onOfflineCheckTimerFired();


        return f_success;
    }
    else
    {
        return f_fail;
    }

}

int ComputerManager::saveOneComputerAlarmLog(ComputerAlarmLog &log)
{
    int ret =  gDBService.saveOneComputerAlarmLog(log);
    lock.lock();
    for (QList<Computer>::iterator iter = computers.begin(); iter != computers.end(); iter++)
    {
        if(iter->id == log.computerId)
        {
            (*iter).unReadALarmCount += 1;
        }
    }

    lock.unlock();

    onOfflineCheckTimerFired();

    return ret;

}

void ComputerManager::deleteOneComputer(long id)
{
    lock.lock();
    QList<Computer>::iterator iter;
    for(iter = computers.begin(); iter != computers.end(); iter++)
    {
        if(iter->id == id)
        {
            gDBService.deleteOneComputer(*iter);
            computers.erase(iter);
            break;
        }
    }
    lock.unlock();

    onOfflineCheckTimerFired();
}

void ComputerManager::onClientReportStatus(SString ip, SString apps)
{
    lock.lock();
    QList<Computer>::iterator iter;
    for (iter = computers.begin(); iter != computers.end(); iter++)
    {
        if(iter->ip == QString::fromStdString(ip))
        {
            iter->lastHeartBeatTime = QDateTime::currentDateTime();
            break;
        }
    }
    lock.unlock();
    if(iter == computers.end())
    {
        Computer computer(QString::fromStdString(ip), ComputerFromSource_autoCreateByTCP, QString::fromStdString(ip), QString(""), QString::fromStdString(apps));

        computer.lastHeartBeatTime = QDateTime::currentDateTime();

        saveOneComputer(computer);
    }
    else if((iter->apps).compare(QString::fromStdString(apps)))
    {
        iter->apps = QString::fromStdString(apps);
        saveOneComputer(*iter);
    }
    else
    {
        onOfflineCheckTimerFired();
    }

}

//int ComputerManager::getOneComputerByID(long id, Computer &computer)
//{
//    int ret = f_fail;
//    lock.lock();
//    QList<Computer>::iterator iter;
//    for(iter = computers.begin(); iter != computers.end(); iter++)
//    {
//        if(iter->id == id)
//        {
//            ret = f_success;
//            computer = *iter;
//            break;
//        }
//    }
//    lock.unlock();

//    return ret;
//}

int ComputerManager::getOneComputerByIP(SString ip, Computer &computer)
{
    int ret = f_fail;
    lock.lock();
    QList<Computer>::iterator iter;
    for(iter = computers.begin(); iter != computers.end(); iter++)
    {
        if(iter->ip.toStdString().compare(ip) == 0)
        {
            ret = f_success;
            computer = *iter;
            break;
        }
    }
    lock.unlock();

    return ret;
}


QList<Computer> ComputerManager::getCopyOfComputers(bool onlyDisConnect, bool onlyUnreadAlarm)
{
    QList<Computer> ret;
    lock.lock();
    foreach (Computer computer, computers) {
        if(onlyDisConnect && onlyUnreadAlarm)
        {
            if(computer.isOffLine() || computer.unReadALarmCount > 0)
            {
                ret.push_back(computer);
            }
        }
        else if (onlyDisConnect && !onlyUnreadAlarm)
        {
            if(computer.isOffLine())
            {
                ret.push_back(computer);
            }
        }
        else if (!onlyDisConnect && onlyUnreadAlarm)
        {
            if(computer.unReadALarmCount > 0)
            {
                ret.push_back(computer);
            }
        }
        else if(!onlyDisConnect && !onlyUnreadAlarm)
        {
            ret.push_back(computer);
        }
    }
    lock.unlock();


    qSort(ret.begin(), ret.end(), compareComputer);
    return ret;
}

QList<Computer> ComputerManager::getCopyOfOnlineComputers(QString appName)
{
    QList<Computer> ret;
    lock.lock();
    foreach (Computer computer, computers) {
        if(!computer.isOffLine())
        {         
            QStringList tmpApps = computer.apps.split(",");
            QList<QString>::Iterator iter;
            for(iter = tmpApps.begin(); iter != tmpApps.end(); iter++)
            {
                if(appName.compare(*iter) == 0)
                {
                    ret.push_back(computer);
                    break;
                }
            }
        }
    }
    lock.unlock();
    return ret;
}

int ComputerManager::getAppRunningInfosFromIP(SString ip, list<AppRunningInfo> &apps)
{
    int ret = f_fail;
    TcpConnectHandler * connect = TcpConnectHandler::connect(ip, CLIENT_LISTEN_PORT,1);
    if(connect == NULL)
    {
        ret = f_fail;
    }
    else
    {
        CommonReq * req = new CommonReq();
        req->type = CommonReq_type_getapprunningstate;
        if(connect->sendMsg(req) == f_success)
        {
            GetAppRunningStateRes * res = (GetAppRunningStateRes *)connect->readMsg();
            if(res)
            {
                ret = f_success;
                apps = res->apps;
            }
            else
            {
                ret = f_fail;
            }

            SafeDeleteObj(res);
        }
        else
        {
            ret = f_fail;
        }
        SafeDeleteObj(req);
        SafeDeleteObj(connect);
    }

    return ret;
}

int ComputerManager::getSystemRunningInfosFromIP(SString ip, list<DiskInfo> &lastDiskInfo,list<float> &lastCPUUsages,list<float> &lastMEMUsages)
{
    int ret = f_fail;
    TcpConnectHandler * connect = TcpConnectHandler::connect(ip, CLIENT_LISTEN_PORT,1);
    if(connect == NULL)
    {
        ret = f_fail;
    }
    else
    {
        CommonReq * req = new CommonReq();
        req->type = CommonReq_type_getsystemrunningstate;
        if(connect->sendMsg(req) == f_success)
        {
            GetSystemRunningStateRes * res = (GetSystemRunningStateRes *)connect->readMsg();
            if(res)
            {
                ret = f_success;
                lastCPUUsages = res->lastCPUUsages;
                lastMEMUsages = res->lastMEMUsages;
                foreach (DiskInfoTlvEncodedObj obj,res->lastDiskInfo) {
                    DiskInfo disk;
                    disk.disk = obj.disk;
                    disk.freeMB = obj.freeMB;
                    disk.totalMB = obj.totalMB;
                    lastDiskInfo.push_back(disk);
                }
            }
            else
            {
                ret = f_fail;
            }

            SafeDeleteObj(res);
        }
        else
        {
            ret = f_fail;
        }
        SafeDeleteObj(req);
        SafeDeleteObj(connect);
    }

    return ret;
}

void ComputerManager::onOneComputerAlarmLogsChanged(long computerId)
{
    lock.lock();
    QList<Computer>::iterator iter;
    for(iter = computers.begin(); iter != computers.end(); iter++)
    {
        if(iter->id  == computerId)
        {
            QString isRead = "0";
            gDBService.loadComputerAlarmLogsCount(iter->unReadALarmCount, &computerId, &isRead,NULL, NULL);
            break;
        }
    }
    lock.unlock();

    onOfflineCheckTimerFired();
}

bool ComputerManager::checkAndSendAlarm()
{
    lock.lock();

    bool ret = false;
    QString content;

    QDateTime now = QDateTime::currentDateTime();
    int totalOffLineCount = 0;

    int totalUnReadAlarmLogCount = 0;
    for (QList<Computer>::iterator iter = computers.begin(); iter != computers.end(); iter++)
    {
        totalOffLineCount += iter->isOffLine();
        totalUnReadAlarmLogCount += iter->unReadALarmCount;

        if(iter->isOffLine() || iter->unReadALarmCount > 0)
        {
           content += getAlarmInfoOfComputer(*iter) + "\n";
        }
    }


    lock.unlock();

    content += "\n\n当前异常告警时间间隔为:" + int2QStr(SEND_EMAIL_INTERVAL_SECONDS) + "秒,期间不再重复发送告警，请尽快处理";

    if(totalOffLineCount > 0 || totalUnReadAlarmLogCount > 0)
    {
        QString title = "告警";
        if(totalOffLineCount > 0)  title += "，当前有" + int2QStr(totalOffLineCount) + "台服务器处于离线状态";
        if(totalUnReadAlarmLogCount > 0) title += "，当前有" + int2QStr(totalUnReadAlarmLogCount) + "条未读异常需要查看";
        QString tos = SEND_EMAIL_TOS;
        sendOutEmail( tos.split(","), title, content);
        ret = true;
    }

    return ret;
}
